package com.airlines.crewassignment.service.linkline.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.airlines.common.ListSortUtil;
import com.airlines.common.MD5Util;
import com.airlines.crewassignment.constant.LinkLineConstant;
import com.airlines.crewassignment.dao.AirPortMapper;
import com.airlines.crewassignment.dao.FlightInfoMapper;
import com.airlines.crewassignment.dao.LinkLineMapper;
import com.airlines.crewassignment.dao.PositionMapper;
import com.airlines.crewassignment.dao.basicinfo.AirPlaneMapper;
import com.airlines.crewassignment.domain.Airport;
import com.airlines.crewassignment.domain.DateTimeRange;
import com.airlines.crewassignment.domain.FlightInfo;
import com.airlines.crewassignment.domain.LinkLine;
import com.airlines.crewassignment.domain.Position;
import com.airlines.crewassignment.domain.Tech;
import com.airlines.crewassignment.domain.util.DutyDurationUtil;
import com.airlines.crewassignment.entity.basicinfo.AirPlane;
import com.airlines.crewassignment.entity.linkline.LinkLineEntity;
import com.airlines.crewassignment.entity.linkline.TaskLoopFlightFact;
import com.airlines.crewassignment.service.basicinfo.FoundationService;
import com.airlines.crewassignment.service.crew.CrewFlightExperienceService;
import com.airlines.crewassignment.service.crew.TechService;
import com.airlines.crewassignment.service.linkline.FlightInfoService;
import com.airlines.crewassignment.service.linkline.FullCalendarService;
import com.airlines.crewassignment.service.linkline.LinkLineService;
import com.airlines.crewassignment.service.linkline.PositionService;
import com.airlines.crewassignment.service.linkline.TaskLoopFlightFactService;

/**
 * @author xxxx
 * @date 2018年3月28日 
 * @description
 */
@Service
public class LinkLineServiceImpl implements LinkLineService{
	@Autowired
	private LinkLineMapper linkLineMapper;
	@Autowired
	private FlightInfoMapper flightInfoMapper;
	@Autowired
	private AirPortMapper airPortMapper;
	@Autowired
	private PositionMapper positionMapper;
/*	@Autowired
	private LinkLineLoopService linkLineLoopService;*/
	@Autowired
	private CrewFlightExperienceService crewFlightExperienceService;
	@Autowired
	private TechService techService;
	@Autowired
	private PositionService positionService;
	@Autowired
	private FlightInfoService flightInfoService;
	@Autowired
	private TaskLoopFlightFactService taskLoopFlightFactService;
	@Autowired
	private FoundationService foundationService;
	@Autowired
	private FullCalendarService fullCalendarService;
	@Autowired
	private AirPlaneMapper airPlaneMapper;
	
	@Override
	public List<LinkLine> listLinkLineBase(String dutyCode,Date flightDate) {
		LinkLineEntity query = new LinkLineEntity();
		query.setFlightDate(flightDate);
		query.setDutyCode(dutyCode);
		List<LinkLine> linkLineList =  linkLineMapper.listLinkLineBase(query);	
		return linkLineList;
	}
	@Override
	public List<LinkLine> listLinkLineAllInfo(String dutyCode,Date flightDate,boolean lastLinkLineInitFlag) {
		//0.查询所有连线基础数据
		List<LinkLine> linkLineBaseList = this.listLinkLineBase(dutyCode,flightDate);
		
		//1.连线主键初始化
		this.crewLinkLineKeyInit(linkLineBaseList);
		
		//2.连线航段查询组装
		this.flightInfoListInit(dutyCode,flightDate, linkLineBaseList);
		
		//2.1该连线所有的任务环航班初始化
		this.flightInfoSameTaskLoopList(dutyCode,linkLineBaseList);
		
		//3.计算连线飞行时间，为各航段STA-STD 之和，单位为分钟
		this.flyDurationInit(linkLineBaseList);
		
		//4.是否是国际航线计算
		this.internationalFlgInit(linkLineBaseList);
		
		//5.机场相关初始化
		this.airportInit(linkLineBaseList);

		//6.本任务号位初始化号位初始化
		this.positionListInit(dutyCode,linkLineBaseList);
		
		//6.1号位最低排班授权初始化
		this.positionTechLowestInit(linkLineBaseList);
		
		//6.2号位最高排班授权初始化
		this.positionTechHighestInit(linkLineBaseList);
		
		//7.本连线批次初始化
		this.batchIndexInit(linkLineBaseList);
		
		//8.本次任务环实例初始化
		//this.linkLineLoopFactInit(linkLineBaseList);
		
		//9.是否是过夜连线初始化
		this.nightPassInit(linkLineBaseList);
		
		//10.taskLoopFact 初始化
		this.taskLoopFactInit(linkLineBaseList);
		
		//11.nightFly 该航线是否夜航
		this.nightFlyInit(linkLineBaseList);

		//12.badRoute 差航线标记
		this.badRouteInit(flightDate,linkLineBaseList);
		
		//12.restLevel 机上休息设施等级
		this.restLevelInit(flightDate,linkLineBaseList);
		
		//99.任务环计算
		//99.1 前置任务计算
	/*	if(lastLinkLineInitFlag){
			this.lastLinkLineInit(linkLineBaseList);
		}*/
		

		
		return linkLineBaseList;
	}
	
	
	/**
	 * 号位最高排班授权初始化
	 * @param linkLineBaseList
	 */
	private void positionTechHighestInit(List<LinkLine> linkLineBaseList) {
		for(LinkLine l :linkLineBaseList){
			for(Position p  : l.getPositionList()){
				Tech t = techService.getTechHighest(p);
				p.setTechHighest(t);
			}
		}
		
	}
	/**
	 * 号位最低排班授权初始化
	 * @param linkLineBaseList
	 */
	private void positionTechLowestInit(List<LinkLine> linkLineBaseList) {
		for(LinkLine l :linkLineBaseList){
			for(Position p  : l.getPositionList()){
				Tech t = techService.getTechLowest(p);
				p.setTechLowest(t);
			}
		}
		
	}
	/**
	 * 连线是否是过夜的初始化
	 * @param linkLineBaseList
	 */
	private void nightPassInit(List<LinkLine> linkLineBaseList) {
	
		//Set<String> loopIdFactSet = new HashSet<>();
		for(LinkLine l:linkLineBaseList){
			//l.setNightPass(false);
			//loopIdFactSet.add(l.getLoopIdFact());
			//FlightInfo flightInfoEndToday = this.getEndFlightInfoToday(l);
			FlightInfo lastFlightInfo = l.getFlightInfoList().get(l.getFlightInfoList().size()-1);
			boolean isBase  = foundationService.isBase(lastFlightInfo.getArrivalAirport(), l.getDutyCode());
//			boolean isNightPass = crewFlightExperienceService.airportIsNightPass(flightInfoEndToday.getArrivalAirport());
			boolean isNightPass = !isBase;
			l.setNightPass(isNightPass);
		}
		
		
//		//如果有连线环，则环的最后一个任务的落地机场判断是否过夜
//		for(String loopIdFact:loopIdFactSet){
//			LinkLine endLinkLine = this.getEndLinkLineForDay(loopIdFact, linkLineBaseList);
//			String linkArrivalAirport = endLinkLine.getLinkArrivalAirport();
//			boolean isNightPass = crewFlightExperienceService.airportIsNightPass(linkArrivalAirport);
//			endLinkLine.setNightPass(isNightPass);
//		}
//		//如果没有连线环，则判断该连线的目的机场是否是过夜
//		for(LinkLine l:linkLineBaseList){
//			if(StringUtils.isBlank(l.getLoopIdFact())){
//				String linkArrivalAirport = l.getLinkArrivalAirport();
//				boolean isNightPass = crewFlightExperienceService.airportIsNightPass(linkArrivalAirport);
//				l.setNightPass(isNightPass);
//			}
//		}
	}
	
	
	
//	private LinkLine getEndLinkLineForDay(String loopIdFact, List<LinkLine> linkLineBaseList){
//		ListSortUtil.sort(linkLineBaseList, false, "ta");
//		for(LinkLine l : linkLineBaseList){
//			if(StringUtils.equals(loopIdFact, l.getLoopIdFact())){
//				return l;
//			}
//		}
//		return null;
//	}
	/**
	 * 本次任务环实例初始化
	 * @param linkLineBaseList
	 */
//	public void linkLineLoopFactInit(List<LinkLine> linkLineBaseList) {
//		for(LinkLine  l : linkLineBaseList){
//			String loopIdFact = l.getLoopIdFact();
//			Integer loopItemId = l.getLoopItemId();
//			
//			if(StringUtils.isNotBlank(loopIdFact) && loopItemId !=null ){
//				LinkLineLoop linkLineLoopFact = linkLineLoopService.getLinkLineLoopFact(loopIdFact, loopItemId);
//				l.setLinkLineLoopFact(linkLineLoopFact);
//			}
//		}
//		
//	}
	/**
	 * 同一个天内同一个航班连线名称的批次的初始化
	 * @param linkLineBaseList
	 */
	private void batchIndexInit(List<LinkLine> linkLineBaseList) {
		for(LinkLine thisL : linkLineBaseList){
			int  batchIndex = this.getBatchIndex(thisL, linkLineBaseList);
			thisL.setBatchIndex(batchIndex);
		}
		
	}
	
	/**
	 * 获取一个连线在同一天连线组内的批次
	 * @param linkLine
	 * @param linkLineBaseList
	 * @return
	 */
	private int getBatchIndex(LinkLine linkLine,List<LinkLine> linkLineBaseList){
		Date thisFlightDate = linkLine.getFlightDate();
		String thisFlightVoyageCode  = linkLine.getFlightVoyageCode();
		DateTime thisTd = new DateTime(linkLine.getTd());
		int batchIndex = 1;
		for(LinkLine otherL : linkLineBaseList){
			String otherFlightVoyageCode  = otherL.getFlightVoyageCode();
			DateTime otherTd =  new DateTime(otherL.getTd()); 
			Date otherFlightDate = otherL.getFlightDate();
			if(thisFlightDate.equals(otherFlightDate)
					&& StringUtils.equals(thisFlightVoyageCode, otherFlightVoyageCode)
					&&otherTd.isBefore(thisTd)
					){
				batchIndex ++;
			}
		}
		
		return batchIndex;
	}


	/**
	 * 前置任务初始化
	 * @param linkLineBaseList
	 */
//	@Deprecated
//	private void lastLinkLineInit1(List<LinkLine> linkLineBaseList) {
//		for(LinkLine linkLine : linkLineBaseList){
//			
//			String loopIdFact = linkLine.getLoopIdFact();
//			Integer loopItemId = linkLine.getLoopItemId();
//			if(StringUtils.isBlank(loopIdFact) || loopItemId == null){
//				continue;
//			}
//			LinkLineLoopItem linkLineLoopItemFact = linkLine.getLinkLineLoopFact().getLoopItemFact();
//			LinkLineLoopItem linkLineLoopItemLast  = linkLineLoopService.getLastloopItem(loopIdFact, loopItemId);
//			LinkLine lastLinkLine ;
//			if(linkLineLoopItemLast == null){
//				lastLinkLine = null;
//			}else if(linkLineLoopItemFact.getDayIndex().equals(linkLineLoopItemLast.getDayIndex())){
//				lastLinkLine  = this.getLastLinkLine(loopIdFact, linkLineLoopItemFact, linkLineLoopItemLast, linkLineBaseList);
//			}else{
//				int dayDiff = linkLineLoopItemFact.getDayIndex() -linkLineLoopItemLast.getDayIndex() ;
//				Date flightDateLast = new DateTime(linkLine.getFlightDate()).minusDays(dayDiff).toDate();
//				List<LinkLine>  lastDateFlightList = this.listLinkLineAllInfo(flightDateLast,false);
//				lastLinkLine  = this.getLastLinkLine(loopIdFact, linkLineLoopItemFact, linkLineLoopItemLast, lastDateFlightList);
//			}
//			
//			linkLine.setLastLinkLineBaseInfo(lastLinkLine);
//		}		
//	}
//	
//	private LinkLine getLastLinkLine(String loopIdFact,LinkLineLoopItem linkLineLoopItemFact,LinkLineLoopItem linkLineLoopItemLast,List<LinkLine> LastLinkLineBaseList){
//		for(LinkLine lastLinkLine : LastLinkLineBaseList){
//			String loopIdFactLast = lastLinkLine.getLoopIdFact();
//			Integer loopItemIdLast = lastLinkLine.getLoopItemId();
//			if(StringUtils.equals(loopIdFact, loopIdFactLast) 
//					&& StringUtils.equals(String.valueOf(linkLineLoopItemLast.getLoopItemId()), String.valueOf(loopItemIdLast))){
//				return lastLinkLine;
//			}
//		}
//		return null;
//	}
	/**
	 * 号位初始化
	 * @param linkLineBaseList
	 */
	@Override
	public void positionListInit(String dutyCode,List<LinkLine> linkLineBaseList) {
		Set<Date> flightDateSet = new HashSet<>();
		for(LinkLine  l : linkLineBaseList){
			flightDateSet.add(l.getFlightDate());
		}
		
		List<Position> positionListAll = new ArrayList<>();
		for(Date flightDate : flightDateSet){
			Position postionQuery = new Position();
			postionQuery.setFlightDate(flightDate);
			postionQuery.setDutyCode(dutyCode);
			List<Position> positionList = positionMapper.listPosition(postionQuery);	
			positionListAll.addAll(positionList);
		}
		
		for(Position p : positionListAll){
			
			String positionKey = positionService.positionKeyInit(p);
			p.setPositionKey(positionKey);
		}
		
		for(LinkLine  l : linkLineBaseList){
			for(Position p : positionListAll){
				if(l.getFlightDate().equals(p.getFlightDate()) && l.getCrewLinkLineNo().equals(p.getCrewLinkLineNo())){
					p.setLinkLine(l);
					p.setCrewLinkLineKey(l.getCrewLinkLineKey());
					l.getPositionList().add(p);
				}
			}
		}
		
		
		
	}
	/**
	 * 连线crewLinkLineKey 初始化
	 * @param linkLineBaseList
	 */
	private void crewLinkLineKeyInit(List<LinkLine> linkLineBaseList){
		for(LinkLine l : linkLineBaseList){
			l.setCrewLinkLineKey(this.crewLinkLineKeyInit(l));
		}
	}
	
	/**
	 * 是否是国际航线计算
	 * @param linkLineBaseList
	 */
	private void internationalFlgInit(List<LinkLine> linkLineList){
		for(LinkLine l : linkLineList){
			boolean internationalFlg = false;
			for(FlightInfo f : l.getFlightInfoList()){
				String dOrI = f.getDorI();
				if(StringUtils.equals(dOrI, LinkLineConstant.DI_I)){
					internationalFlg = true;
				}
			}
			l.setInternationalFlg(internationalFlg);
		}
	}
	
	/**
	 * 连线飞行时间初始化
	 * @param linkLineList
	 */
	private void flyDurationInit(List<LinkLine> linkLineList){
		for(LinkLine ll : linkLineList){
			int flyDuration = 0;
			for(FlightInfo f : ll.getFlightInfoList()){
				flyDuration += f.getFlightDuration();
			}
			ll.setFlyDuration(flyDuration);
		}
	}
	
	/**
	 * 航班详情列表初始化
	 * @param flightDate
	 * @param linkLineList
	 */
	@Override
	public void flightInfoListInit(String dutyCode,Date flightDate, List<LinkLine> linkLineList){
		FlightInfo flightInfoQuery = new FlightInfo();
		flightInfoQuery.setFlightDate(flightDate);
		List<FlightInfo>  flightInfoList = flightInfoMapper.listFlightInfo(flightInfoQuery);
		ListSortUtil.sort(flightInfoList, true, "std");
		
		//计算每个航段的飞行时间
		for(FlightInfo  f : flightInfoList){
			int flightDuration  =flightInfoService.getFlightDuration(f);
			f.setFlightDuration(flightDuration);
		}
		//任务环匹配
		taskLoopFlightFactService.flightInfoTaskLoopFlightFactListInit(dutyCode,flightInfoList);
		
		//全部人员匹配
		DateTimeRange dtr= new DateTimeRange(flightDate,flightDate);
		List<FlightInfo> flightInfoListForCrewWorkcodesAll = flightInfoMapper.listFlithtInfoOfCrewWorkcodesAll(dtr);
		for(FlightInfo  f : flightInfoList){
			for(FlightInfo fcw : flightInfoListForCrewWorkcodesAll){
				if(f.getFlightId().equals(fcw.getFlightId())){
					f.setCrewWorkcodesAll(fcw.getCrewWorkcodesAll());
				}
			}
		}
		
		
		for(LinkLine ll : linkLineList){
			for(FlightInfo f : flightInfoList){
				int flightInfoCrewLinkLineNo = flightInfoService.getCrewLinkLineNo(f, dutyCode);
				if(ll.getFlightDate().equals(f.getFlightDate()) && ll.getCrewLinkLineNo().equals(flightInfoCrewLinkLineNo)){
					ll.getFlightInfoList().add(f);
				}
			}
		}
	}
	
	/**
	 * 机场相关初始化
	 * @param linkLineList
	 */
	private void airportInit(List<LinkLine> linkLineList){
		List<Airport> specialAirPortList = airPortMapper.listAllSpecialAirport();

		for(LinkLine l : linkLineList){
			//1.连线上所有机场
			Set<String> linkLineAirportList = new HashSet<>();
			List<FlightInfo> flightInfoList = l.getFlightInfoList();
			for(FlightInfo f : flightInfoList){
				String departureAirport = f.getDepartureAirport(); //起飞机场
				String arrivalAirport = f.getArrivalAirport(); //落地机场
				linkLineAirportList.add(departureAirport);
				linkLineAirportList.add(arrivalAirport);
			}
			l.getAirportList().addAll(linkLineAirportList);
			

			//2.连线上所有特殊机场
			Set<String> specialAirportList = new HashSet<>();
			for(String linkLineAirport : linkLineAirportList){
				boolean specialFlag = false;
				for(Airport specialAirport : specialAirPortList){
					if(StringUtils.equals(linkLineAirport, specialAirport.getAirport4Code())){
						specialFlag = true;
					}
				}
				
				if(specialFlag){
					specialAirportList.add(linkLineAirport);
				}
			}
			l.getSpecialAirportList().addAll(specialAirportList);
		}
		
	}
//	@Override
//	public List<LinkLine> initLinkLineLoopFact(Date flightDate) {
//		//0.查询所有连线基础数据
//		List<LinkLine> linkLineBaseList = this.listLinkLineBase(flightDate);
//		this.batchIndexInit(linkLineBaseList);
//		
//		List<LinkLineLoop>  allLinkLineLoopList = linkLineLoopService.listLinkLineLoopAllInfo();
//		
//		List<LinkLine> linkLineNoLoopList = new ArrayList<>();
//		
//		for(LinkLine l : linkLineBaseList){
//			LinkLineLoop linkLineLoopFact = linkLineLoopService.getLinkLineLoopFact(flightDate, l.getBatchIndex(), l.getFlightVoyageCode(), allLinkLineLoopList);
//			if(linkLineLoopFact != null)
//			{
//				l.setLinkLineLoopFact(linkLineLoopFact);
//				l.setLoopIdFact(linkLineLoopFact.getLoopIdFact());
//				l.setLoopItemId(linkLineLoopFact.getLoopItemFact().getLoopItemId());
//			}else{
//				linkLineNoLoopList.add(l);
//			}	
//		}
//		
//		
//		//如果没有查询到，则可能是连线拆分了，拆分后如何做？ 将所有的连线按照时间排序后，尝试组合，看看能否组合成已经定义的任务环
//		ListSortUtil.sort(linkLineNoLoopList, true, "td");
//		for(int i = 0 ; i<linkLineNoLoopList.size() ; i++){
//			LinkLine thisL = linkLineNoLoopList.get(i);
//			int thisBatchIndex = thisL.getBatchIndex();
//			String thisFlightVoyageCode = thisL.getFlightVoyageCode();
//			LinkLineLoop linkLineLoopFact = null;
//			otherFor:
//			for(int j = i+1; j <linkLineNoLoopList.size() ; j++){
//				LinkLine otherL = linkLineNoLoopList.get(j);
//				String  otherFlightVoyageCode = otherL.getFlightVoyageCode();
//				String flightVoyageCode = thisFlightVoyageCode+otherFlightVoyageCode.substring(4);
//				linkLineLoopFact = linkLineLoopService.getLinkLineLoopFact(flightDate, thisBatchIndex, flightVoyageCode, allLinkLineLoopList);
//				if(linkLineLoopFact != null)
//				{
//					thisL.setLinkLineLoopFact(linkLineLoopFact);
//					thisL.setLoopIdFact(linkLineLoopFact.getLoopIdFact());
//					thisL.setLoopItemId(linkLineLoopFact.getLoopItemFact().getLoopItemId());
//					
//					otherL.setLinkLineLoopFact(linkLineLoopFact);
//					otherL.setLoopIdFact(linkLineLoopFact.getLoopIdFact());
//					otherL.setLoopItemId(linkLineLoopFact.getLoopItemFact().getLoopItemId());
//					
//					break otherFor;
//				}
//			}			
//		}
//		
//		//如果还没有，则应是一些临时航班，则不做任务环，人员手动排班
//		
//		//查询上一次任务
//		for(LinkLine thisLinkLine : linkLineBaseList){
//			String loopIdFact = thisLinkLine.getLoopIdFact();
//			Integer loopItemId = thisLinkLine.getLoopItemId();
//			if(StringUtils.isBlank(loopIdFact) || loopItemId == null){
//				continue ;
//			}
//			
//			LinkLineLoopItem linkLineLoopItemLast  = linkLineLoopService.getLastloopItem(loopIdFact, loopItemId);
//			if(linkLineLoopItemLast == null){
//				continue ;
//			}
//			Integer lastIoopItemId = linkLineLoopItemLast.getLoopItemId();
//			
//			LinkLine lastLinkLineBaseInfo = linkLineMapper.getLastLinkLine(thisLinkLine,loopIdFact,lastIoopItemId);
//			thisLinkLine.setLastLinkLineBaseInfo(lastLinkLineBaseInfo);
//			
//		}
//		
//	
//		//保存到数据库
//		for(LinkLine l : linkLineBaseList){
//			linkLineMapper.updateLoopIdFactF(l.getFlightDate(), l.getCrewLinkLineNo(), l.getLoopIdFact(), l.getLoopItemId(),l.getLastLinkLineBaseInfo());
//		}
//		
//		ListSortUtil.sort(linkLineBaseList, true, "td");
//		return linkLineBaseList;
//	}
	
	@Override
	public void initLastLinkLine(LinkLine thisLinkLine, Date beforeFlightDate) {
//		String loopIdFact = thisLinkLine.getLoopIdFact();
//		Integer loopItemId = thisLinkLine.getLoopItemId();
//		if(StringUtils.isBlank(loopIdFact) || loopItemId == null){
//			return ;
//		}
//		
//		LinkLineLoopItem linkLineLoopItemLast  = linkLineLoopService.getLastloopItem(loopIdFact, loopItemId);
//		if(linkLineLoopItemLast == null){
//			return ;
//		}
//		Integer lastIoopItemId = linkLineLoopItemLast.getLoopItemId();
		
//		LinkLine lastLinkLine = linkLineMapper.getLastLinkLine(thisLinkLine,loopIdFact,lastIoopItemId);
		
		LinkLine lastLinkLine  = this.getLastLinkLineBySameTaskLoop(thisLinkLine);
		if(lastLinkLine == null){
			return ;
		}
		String crewLinkLineKey = this.crewLinkLineKeyInit(lastLinkLine);
		lastLinkLine.setCrewLinkLineKey(crewLinkLineKey);
		
		//如果是排班开始日期前的，则将workcode算出来
		if(lastLinkLine.getFlightDate().before(beforeFlightDate)){
			Position postionQuery = new Position();
			postionQuery.setFlightDate(lastLinkLine.getFlightDate());
			postionQuery.setCrewLinkLineNo(lastLinkLine.getCrewLinkLineNo());
			postionQuery.setDutyCode(thisLinkLine.getDutyCode());
			
			List<Position> positionList = positionMapper.listPosition(postionQuery);
			Set<String> lastWorkcodeSet = new HashSet<>();
			for(Position  p : positionList ){
				lastWorkcodeSet.add(p.getWorkcode());
			}
			
			thisLinkLine.setLastWorkcodeSet(lastWorkcodeSet);
		}	
		
		thisLinkLine.setLastLinkLineBaseInfo(lastLinkLine);
		
	}
	
	@Override
	public String crewLinkLineKeyInit(LinkLine l) {
		return MD5Util.md5Encode(l.getDutyCode()+l.getFlightDate().toString()+l.getCrewLinkLineNo());
	}
	@Override
	public LinkLine getLinkLine(Date flightDate, int crewLinkLine, String dutyCode) {
		return linkLineMapper.getLinkLine(flightDate,crewLinkLine,dutyCode);
	}
	

	/**
	 * 初始化构造同一个任务环的航班
	 * @param linkLineBaseList
	 */
	@Override
	public void flightInfoSameTaskLoopList(String dutyCode,List<LinkLine> linkLineBaseList) {
		for(LinkLine l : linkLineBaseList){
			Set<String> taskLoopFactSet = new HashSet<>();
			for(FlightInfo f : l.getFlightInfoList()){
				String taskLoopFact = flightInfoService.getTaskLoopFact(f, dutyCode);
				if(StringUtils.isNotBlank(taskLoopFact)){
					taskLoopFactSet.add(taskLoopFact);
				}
			}
			List<FlightInfo> flightInfoSameTaskLoopList = new ArrayList<>();
			for(String taskLoopFact : taskLoopFactSet){
				List<FlightInfo>  temp =flightInfoMapper.listFlightInfoByTaskLoopFact(dutyCode, taskLoopFact);
				flightInfoSameTaskLoopList.addAll(temp);
			}
			ListSortUtil.sort(flightInfoSameTaskLoopList, true, "std");
			l.setFlightInfoSameTaskLoopList(flightInfoSameTaskLoopList);
		}
	}
	
	/**
	 * 获取某个连线上任务环航班的最后一个航班
	 * @return
	 */
	private FlightInfo getEndFlightInfoToday(LinkLine l){
		List<FlightInfo> flightInfoSameTaskLoopList  = l.getFlightInfoSameTaskLoopList();
		if(CollectionUtils.isEmpty(flightInfoSameTaskLoopList)){
			List<FlightInfo> flightInfoList = l.getFlightInfoList();
			return flightInfoList.get(flightInfoList.size()-1);
		}else{
			Date flightDate = l.getFlightDate();
			List<FlightInfo> flightInfoSameTaskLoopListToday  = new ArrayList<>();;
			for(FlightInfo f : flightInfoSameTaskLoopList){
				if(f.getFlightDate().equals(flightDate)){
					flightInfoSameTaskLoopListToday.add(f);
				}
			}
			return flightInfoSameTaskLoopListToday.get(flightInfoSameTaskLoopListToday.size()-1);
		}
	}
	
	/**
	 * 获取本连线的上一个航班
	 * @return
	 */
	private FlightInfo getLastFlightInfoBeforeThisLinkLine(LinkLine l){
		List<FlightInfo> flightInfoSameTaskLoopList  = l.getFlightInfoSameTaskLoopList();
		FlightInfo fristFlightInfo = l.getFlightInfoList().get(0);
		List<FlightInfo> flightInfoSameTaskLoopListBeforeToday  = new ArrayList<>();;
		for(FlightInfo f : flightInfoSameTaskLoopList){
			if(f.getStd().before(fristFlightInfo.getStd())){
				flightInfoSameTaskLoopListBeforeToday.add(f);
			}
		}
		if(CollectionUtils.isEmpty(flightInfoSameTaskLoopListBeforeToday)){
			return null;
		}else{
			return flightInfoSameTaskLoopListBeforeToday.get(flightInfoSameTaskLoopListBeforeToday.size()-1);
		}
	}
	
	private LinkLine getLastLinkLineBySameTaskLoop(LinkLine l){
		FlightInfo f = this.getLastFlightInfoBeforeThisLinkLine(l);
		if(f == null){
			return null;
		}else{
			int crewLinkLine = flightInfoService.getCrewLinkLineNo(f, l.getDutyCode());
			return linkLineMapper.getLinkLine(f.getFlightDate(), crewLinkLine, l.getDutyCode());
		}
	}
	
	private void taskLoopFactInit(List<LinkLine> linkLineBaseList){
		for(LinkLine l : linkLineBaseList){
			List<FlightInfo> flightInfoSameTaskLoopList  = l.getFlightInfoSameTaskLoopList();
			Set<String> taskLoopFactSet = new HashSet<>();
			for(FlightInfo f : flightInfoSameTaskLoopList){
				String taskLoopFact  = flightInfoService.getTaskLoopFact(f, l.getDutyCode());
				taskLoopFactSet.add(taskLoopFact);
//				if(StringUtils.equals(l.getDutyCode(), CrewConstant.DUTY_F)){
//					taskLoopFactSet.add(f.getTaskLoopFactF());
//				}
//				if(StringUtils.equals(l.getDutyCode(), CrewConstant.DUTY_C)){
//					taskLoopFactSet.add(f.getTaskLoopFactC());
//				}
//				if(StringUtils.equals(l.getDutyCode(), CrewConstant.DUTY_A)){
//					taskLoopFactSet.add(f.getTaskLoopFactA());
//				}	
			}
			
			if(taskLoopFactSet.size() >= 1){
				String taskLoopFact = "";
				for(String s : taskLoopFactSet){
					taskLoopFact = taskLoopFact + s;
				}
				l.setTaskLoopFact(taskLoopFact);
			}	
		}
	}
	
	private void nightFlyInit(List<LinkLine> linkLineBaseList){
		for(LinkLine l : linkLineBaseList){
			boolean isNightFly = false;
			for(FlightInfo f : l.getFlightInfoList()){
				if(flightInfoService.isNightFly(f)){
					isNightFly = true;
				}
			}
			l.setNightFly(isNightFly);
		}
	}
	
	/**
	 * 是否是差连线初始化
	 * @param flightDate
	 * @param linkLineBaseList
	 */
	private void badRouteInit(Date flightDate,List<LinkLine> linkLineBaseList){
		for(LinkLine l : linkLineBaseList){
			boolean badRoute = false;
			FlightInfoFor:
			for(FlightInfo f : l.getFlightInfoList()){
				for(TaskLoopFlightFact tlff : f.getTaskLoopFlightFactList()){
					if(f.getFlightId().equals(tlff.getFlightId())
							&& StringUtils.equals(tlff.getModuleFlag(),l.getDutyCode())
							&& tlff.getBadRoute()!=null 
							&& tlff.getBadRoute() == true){
						badRoute = true;
						break  FlightInfoFor;
					}	
				}
			}
			l.setBadRoute(badRoute);
		}
	}
	@Override
	public int getDutyDuration(String dutyCode, Date flightDate, int crewLinkLineNo) {
		//1.查询同一个连线下相同任务环的航班列表
		List<FlightInfo> flightInfoList = fullCalendarService.listFlightBySameTaskLoopFactSameFlightDate(dutyCode, flightDate, crewLinkLineNo);
		//任务环匹配
		taskLoopFlightFactService.flightInfoTaskLoopFlightFactListInit(dutyCode,flightInfoList);
		
		ListSortUtil.sort(flightInfoList, true, "std");
		//计算每天的执勤期
		return DutyDurationUtil.getDutyDurationByFlightInfo(dutyCode, flightInfoList);
	}
	
	
	/**
	 * 机上设施休息等级初始化
	 * @param flightDate
	 * @param linkLineBaseList
	 */
	private void restLevelInit(Date flightDate, List<LinkLine> linkLineBaseList) {
		List<AirPlane> airPlaneList = airPlaneMapper.listAll();
		for(LinkLine l : linkLineBaseList){
			for(AirPlane a : airPlaneList){
				if(StringUtils.equals(l.getAcReg(), a.getAcReg())){
					l.setRestLevel(a.getRestLevel());
				}
			}
		}
	}
}
